home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / dkb32.zip / DKB32SRC.ZIP / RENDER.C < prev    next >
C/C++ Source or Header  |  1992-01-27  |  15KB  |  469 lines

  1. /*****************************************************************************
  2. *
  3. *                                    render.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements the main raytracing loop.
  8. *
  9. * This software is freely distributable. The source and/or object code may be
  10. * copied or uploaded to communications services so long as this notice remains
  11. * at the top of each file.  If any changes are made to the program, you must
  12. * clearly indicate in the documentation and in the programs startup message
  13. * who it was who made the changes. The documentation should also describe what
  14. * those changes were. This software may not be included in whole or in
  15. * part into any commercial package without the express written consent of the
  16. * author.  It may, however, be included in other public domain or freely
  17. * distributed software so long as the proper credit for the software is given.
  18. *
  19. * This software is provided as is without any guarantees or warranty. Although
  20. * the author has attempted to find and correct any bugs in the software, he
  21. * is not responsible for any damage caused by the use of the software.  The
  22. * author is under no obligation to provide service, corrections, or upgrades
  23. * to this package.
  24. *
  25. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  26. * about them.  Also, if you have any comments or questions, you may contact me
  27. * at the following address:
  28. *
  29. *     David Buck
  30. *     22C Sonnet Cres.
  31. *     Nepean Ontario
  32. *     Canada, K2H 8W7
  33. *
  34. *  I can also be reached on the following bulleton boards:
  35. *
  36. *     OMX              (613) 731-3419
  37. *     Mystic           (613) 596-4249  or  (613) 596-4772
  38. *
  39. *  Fidonet:   1:163/109.9
  40. *  Internet:  dbuck@ccs.carleton.ca
  41. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     The "You Can Call Me RAY" BBS (708) 358-5611
  46. *     The Information Exchange BBS  (708) 945-5575
  47. *
  48. *****************************************************************************/
  49.  
  50. #include <signal.h>
  51. #include <time.h>
  52. #include "frame.h"
  53. #include "vector.h"
  54. #include "dkbproto.h"
  55.  
  56. extern FILE_HANDLE *Output_File_Handle;
  57. extern char Output_File_Name[FILE_NAME_LENGTH];
  58. extern char OutputFormat;
  59. extern int File_Buffer_Size;
  60. extern unsigned int Options;
  61. extern int Quality;
  62. volatile int Stop_Flag;
  63. extern int First_Line, Last_Line;
  64. extern long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  65. extern short *hashTable;
  66. extern unsigned short crctab[256];
  67.  
  68. #define rand3d(a,b) crctab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
  69. #define MAX_TRACE_LEVEL 5
  70.  
  71. void Output_Line PARAMS((int y, COLOUR **Previous_Line, COLOUR **Current_Line,
  72.     char **Previous_Line_Antialiased_Flags,
  73.     char **Current_Line_Antialiased_Flags));
  74. extern void print_line_stats PARAMS ((register int y));
  75.  
  76. COLOUR *Previous_Line, *Current_Line;
  77. char *Previous_Line_Antialiased_Flags, *Current_Line_Antialiased_Flags;
  78. RAY Ray;
  79. FRAME Frame;
  80. RAY *VP_Ray;
  81. int Trace_Level, SuperSampleCount;
  82. time_t  Start_Time, Previous_Time;
  83.  
  84. void Create_Ray (ray, width, height, x, y)
  85.     RAY *ray;
  86.     int width, height;
  87.     DBL x, y;
  88.     {
  89.     register DBL X_Scalar, Y_Scalar;
  90.     VECTOR Temp_Vect_1, Temp_Vect_2;
  91.  
  92.     /* Convert the X Coordinate to be a DBL from 0.0 to 1.0 */
  93.     X_Scalar = (x - (DBL) width / 2.0) / (DBL) width;
  94.  
  95.     /* Convert the Y Coordinate to be a DBL from 0.0 to 1.0 */
  96.     Y_Scalar = (( (DBL)(Frame.Screen_Height - 1) - y) -
  97.             (DBL) height / 2.0) / (DBL) height;
  98.  
  99.     VScale (Temp_Vect_1, Frame.View_Point.Up, Y_Scalar);
  100.     VScale (Temp_Vect_2, Frame.View_Point.Right, X_Scalar);
  101.     VAdd (ray->Direction, Temp_Vect_1, Temp_Vect_2);
  102.     VAdd (ray->Direction, ray->Direction, Frame.View_Point.Direction);
  103.     VNormalize (ray->Direction, ray->Direction);
  104.     Initialize_Ray_Containers (ray);
  105.     ray->Quadric_Constants_Cached = FALSE;
  106.     }
  107.  
  108.  
  109. void Supersample (result, x, y, Width, Height)
  110.     COLOUR *result;
  111.     int x, y, Width, Height;
  112.     {
  113.     COLOUR colour;
  114.     register DBL dx, dy, Jitter_X, Jitter_Y;
  115.  
  116.     dx = (DBL) x;
  117.     dy = (DBL) y;
  118.  
  119.     Number_Of_Pixels_Supersampled++;
  120.  
  121.     Make_Colour (result, 0.0, 0.0, 0.0);
  122.  
  123.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  124.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  125.     Create_Ray (VP_Ray, Frame.Screen_Width, Frame.Screen_Height,
  126.                 dx + Jitter_X, dy + Jitter_Y);
  127.  
  128.     Trace_Level = 0;
  129.     Trace (VP_Ray, &colour);
  130.     Clip_Colour (&colour, &colour);
  131.     Scale_Colour (&colour, &colour, 0.11111111);
  132.     Add_Colour (result, result, &colour);
  133.  
  134.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  135.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  136.     Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  137.                                                 dy + Jitter_Y - 0.3333333);
  138.     Trace_Level = 0;
  139.     Trace (VP_Ray, &colour);
  140.     Clip_Colour (&colour, &colour);
  141.     Scale_Colour (&colour, &colour, 0.11111111);
  142.     Add_Colour (result, result, &colour);
  143.  
  144.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  145.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  146.     Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  147.                                                 dy + Jitter_Y);
  148.     Trace_Level = 0;
  149.     Trace (VP_Ray, &colour);
  150.     Clip_Colour (&colour, &colour);
  151.     Scale_Colour (&colour, &colour, 0.11111111);
  152.     Add_Colour (result, result, &colour);
  153.  
  154.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  155.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  156.     Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  157.                                                 dy + Jitter_Y + 0.3333333);
  158.     Trace_Level = 0;
  159.     Trace (VP_Ray, &colour);
  160.     Clip_Colour (&colour, &colour);
  161.     Scale_Colour (&colour, &colour, 0.11111111);
  162.     Add_Colour (result, result, &colour);
  163.  
  164.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  165.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  166.     Create_Ray (VP_Ray, Width, Height, dx + Jitter_X,
  167.                                                 dy + Jitter_Y - 0.3333333);
  168.     Trace_Level = 0;
  169.     Trace (VP_Ray, &colour);
  170.     Clip_Colour (&colour, &colour);
  171.     Scale_Colour (&colour, &colour, 0.11111111);
  172.     Add_Colour (result, result, &colour);
  173.  
  174.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  175.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  176.     Create_Ray (VP_Ray, Width, Height, dx + Jitter_X,
  177.                                                 dy + Jitter_Y + 0.3333333);
  178.     Trace_Level = 0;
  179.     Trace (VP_Ray, &colour);
  180.     Clip_Colour (&colour, &colour);
  181.     Scale_Colour (&colour, &colour, 0.11111111);
  182.     Add_Colour (result, result, &colour);
  183.  
  184.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  185.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  186.     Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  187.                                                 dy + Jitter_Y - 0.3333333);
  188.     Trace_Level = 0;
  189.     Trace (VP_Ray, &colour);
  190.     Clip_Colour (&colour, &colour);
  191.     Scale_Colour (&colour, &colour, 0.11111111);
  192.     Add_Colour (result, result, &colour);
  193.  
  194.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  195.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  196.     Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  197.                                                 dy + Jitter_Y);
  198.     Trace_Level = 0;
  199.     Trace (VP_Ray, &colour);
  200.     Clip_Colour (&colour, &colour);
  201.     Scale_Colour (&colour, &colour, 0.11111111);
  202.     Add_Colour (result, result, &colour);
  203.  
  204.     Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  205.     Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  206.     Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  207.                                                 dy + Jitter_Y + 0.3333333);
  208.     Trace_Level = 0;
  209.     Trace (VP_Ray, &colour);
  210.     Clip_Colour (&colour, &colour);
  211.     Scale_Colour (&colour, &colour, 0.11111111);
  212.     Add_Colour (result, result, &colour);
  213.     }
  214.  
  215. void initialize_renderer()
  216.     {
  217.     allocate_lines(&Previous_Line, &Current_Line, &Previous_Line_Antialiased_Flags, &Current_Line_Antialiased_Flags, &Ray);
  218.     }
  219.  
  220. void Read_Rendered_Part()
  221.     {
  222.     int rc, x, line_number;
  223.     char Red, Green, Blue;
  224.  
  225.     while ((rc = Read_Line(Output_File_Handle, Previous_Line, &line_number)) == 1) {
  226.         if (Options & DISPLAY)
  227.             for (x = 0 ; x < Frame.Screen_Width ; x++) {
  228.                 Red = (char) (Previous_Line[x].Red * 255.0);
  229.                 Green = (char) (Previous_Line[x].Green * 255.0);
  230.                 Blue = (char) (Previous_Line[x].Blue * 255.0);
  231.                 display_plot (x, line_number, Red, Green, Blue);
  232.                 }
  233.         }
  234.  
  235.     First_Line = line_number+1;
  236.  
  237.     if (rc == 0) {
  238.         Close_File(Output_File_Handle);
  239.         if (Open_File (Output_File_Handle, Output_File_Name,
  240.                 &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  241.                 APPEND_MODE) != 1) {
  242.             fprintf (stderr, "Error opening output file\n");
  243.             exit(1);
  244.             }
  245.         return;
  246.         }
  247.  
  248.     fprintf (stderr, "Error reading aborted data file\n");
  249.     }
  250.  
  251. void control_c_was_pressed (int iDontKnow) {
  252.     Stop_Flag = TRUE;
  253. /* do not set SIGINT again so that a second */
  254. /* control c will terminate the process */
  255. }
  256.  
  257. void Start_Tracing ()
  258.     {
  259.     COLOUR Colour;
  260.     register int x, y;
  261.     char Red, Green, Blue, Antialias_Center_Flag;
  262.  
  263.     /* signal (SIGINT, control_c_was_pressed); */
  264.  
  265.         Start_Time = Previous_Time = time (NULL);
  266.  
  267.     for (y = (Options & ANTIALIAS)?First_Line-1:First_Line; y<Last_Line; y++) {
  268.  
  269.         if (Options & ANTIALIAS)
  270.             SuperSampleCount = 0;
  271.  
  272.         for (x = 0 ; x < Frame.Screen_Width ; x++) {
  273.             Number_Of_Pixels++;
  274.             if (Stop_Flag) {
  275.                 close_all();
  276.                 exit(0);
  277.             }
  278.  
  279.             /* TEST_ABORT */
  280.  
  281.             Create_Ray (VP_Ray, Frame.Screen_Width, Frame.Screen_Height, (DBL) x, (DBL) y);
  282.             Trace_Level = 0;
  283.             Trace (&Ray, &Colour);
  284.             Clip_Colour (&Colour, &Colour);
  285.  
  286.             Current_Line[x] = Colour;
  287.  
  288.             if (Options & ANTIALIAS) {
  289.                 Antialias_Center_Flag = 0;
  290.                 Current_Line_Antialiased_Flags[x] = 0;
  291.  
  292.                 if (x != 0) {
  293.                     if (Colour_Distance (&Current_Line[x-1], &Current_Line[x])
  294.                         >= Frame.Antialias_Threshold) {
  295.                         Antialias_Center_Flag = 1;
  296.                         if (!(Current_Line_Antialiased_Flags[x-1])) {
  297.                             Supersample (&Current_Line[x-1], 
  298.                                             x-1, y, Frame.Screen_Width, Frame.Screen_Height);
  299.                             Current_Line_Antialiased_Flags[x-1] = 1;
  300.                             SuperSampleCount++;
  301.                             }
  302.                         }
  303.                     }
  304.  
  305.                 if (y != First_Line-1) {
  306.                     if (Colour_Distance (&Previous_Line[x], &Current_Line[x])
  307.                         >= Frame.Antialias_Threshold) {
  308.                         Antialias_Center_Flag = 1;
  309.                         if (!(Previous_Line_Antialiased_Flags[x])) {
  310.                             Supersample (&Previous_Line[x],
  311.                                             x, y-1, Frame.Screen_Width, Frame.Screen_Height);
  312.                             Previous_Line_Antialiased_Flags[x] = 1;
  313.                             SuperSampleCount++;
  314.                             }
  315.                         }
  316.                     }
  317.  
  318.                 if (Antialias_Center_Flag) {
  319.                     Supersample (&Current_Line[x],
  320.                                     x, y, Frame.Screen_Width, Frame.Screen_Height);
  321.                     Current_Line_Antialiased_Flags[x] = 1;
  322.                     Colour = Current_Line[x];
  323.                     SuperSampleCount++;
  324.                     }
  325.                 }
  326.  
  327.             if (y != First_Line-1) {
  328.                 Red = (char) (Colour.Red * 255.0);
  329.                 Green = (char) (Colour.Green * 255.0);
  330.                 Blue = (char) (Colour.Blue * 255.0);
  331.  
  332.                 if (Options & DISPLAY)
  333.                     display_plot (x, y, Red, Green, Blue);
  334.                 }
  335.             }
  336.         Output_Line(y, &Previous_Line, &Current_Line, &Previous_Line_Antialiased_Flags, &Current_Line_Antialiased_Flags);
  337.  
  338.         if (Options & VERBOSE)
  339.             print_line_stats (y);
  340.  
  341.         }
  342.  
  343.     if (Options & DISKWRITE) {
  344.         Write_Line (Output_File_Handle, Previous_Line, Last_Line - 1);
  345.         }
  346.     }
  347.  
  348. void  allocate_lines(Previous_Line, Current_Line, Previous_Line_Antialiased_Flags, Current_Line_Antialiased_Flags, Ray)
  349.     COLOUR **Previous_Line, **Current_Line;
  350.     char **Previous_Line_Antialiased_Flags, **Current_Line_Antialiased_Flags;
  351.     RAY *Ray;
  352.     {
  353.     register int i;
  354.  
  355.     VP_Ray = Ray;
  356.  
  357.     *Previous_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  358.     *Current_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  359.  
  360.     for (i = 0 ; i <= Frame.Screen_Width ; i++) {
  361.         (*Previous_Line)[i].Red = 0.0;
  362.         (*Previous_Line)[i].Green = 0.0;
  363.         (*Previous_Line)[i].Blue = 0.0;
  364.  
  365.         (*Current_Line)[i].Red = 0.0;
  366.         (*Current_Line)[i].Green = 0.0;
  367.         (*Current_Line)[i].Blue = 0.0;
  368.         }
  369.  
  370.     if (Options & ANTIALIAS) {
  371.         *Previous_Line_Antialiased_Flags =
  372.             (char *) malloc (sizeof (char)*(Frame.Screen_Width + 1));
  373.         *Current_Line_Antialiased_Flags =
  374.             (char *)  malloc (sizeof (char)*(Frame.Screen_Width + 1));
  375.  
  376.         for (i = 0 ; i <= Frame.Screen_Width ; i++) {
  377.             (*Previous_Line_Antialiased_Flags)[i] = 0;
  378.             (*Current_Line_Antialiased_Flags)[i] = 0;
  379.             }
  380.     }
  381.  
  382.     Ray->Initial = Frame.View_Point.Location;
  383.     return;
  384.     }
  385.  
  386. void Output_Line (y, Previous_Line, Current_Line, Previous_Line_Antialiased_Flags, Current_Line_Antialiased_Flags)
  387.     register int y;
  388.     COLOUR **Previous_Line, **Current_Line;
  389.     char **Previous_Line_Antialiased_Flags, **Current_Line_Antialiased_Flags;
  390.     {
  391.         COLOUR *Temp_Colour_Ptr;
  392.         char *Temp_Char_Ptr;
  393.  
  394.         if (Options & DISKWRITE)
  395.             if (y > First_Line) {
  396.                 Write_Line (Output_File_Handle, *Previous_Line, y-1);
  397.             }
  398.  
  399.         if (Options & VERBOSE)
  400.             if (Options & ANTIALIAS)
  401.                 printf (" supersampled %d times\n", SuperSampleCount);
  402.             else
  403.                 putchar ('\n');
  404.  
  405.         Temp_Colour_Ptr = *Previous_Line;
  406.         *Previous_Line = *Current_Line;
  407.         *Current_Line = Temp_Colour_Ptr;
  408.  
  409.         Temp_Char_Ptr = *Previous_Line_Antialiased_Flags;
  410.         *Previous_Line_Antialiased_Flags = *Current_Line_Antialiased_Flags;
  411.         *Current_Line_Antialiased_Flags = Temp_Char_Ptr;
  412.  
  413.         return;
  414.     }
  415.  
  416. void Trace (Ray, Colour)
  417.     RAY *Ray;
  418.     COLOUR *Colour;
  419.     {
  420.     OBJECT *Object;
  421.     INTERSECTION *Local_Intersection, *New_Intersection;
  422.     register int Intersection_Found;
  423.  
  424.     Number_Of_Rays++;
  425.     Make_Colour (Colour, 0.0, 0.0, 0.0);
  426.  
  427.     Intersection_Found = FALSE;
  428.     Local_Intersection = NULL;
  429.  
  430.     if (Trace_Level > MAX_TRACE_LEVEL) {
  431.         return;
  432.         }
  433.  
  434.     if (Frame.Fog_Distance == 0.0) {
  435.         Make_Colour (Colour, 0.0, 0.0, 0.0);
  436.         }
  437.     else
  438.         *Colour = Frame.Fog_Colour;
  439.  
  440.     if (Options & DEBUGGING)
  441.         printf ("Calculating intersections level %d\n", Trace_Level);
  442.  
  443.     /* What objects does this ray intersect? */
  444.     for (Object = Frame.Objects ; 
  445.         Object != NULL ;
  446.         Object = Object -> Next_Object) {
  447.  
  448.         if (New_Intersection = Intersection (Object, Ray)) {
  449.             if (Intersection_Found) {
  450.                 if (Local_Intersection -> Depth > New_Intersection -> Depth) {
  451.                     free (Local_Intersection);
  452.                     Local_Intersection = New_Intersection;
  453.                     }
  454.                 else
  455.                     free (New_Intersection);
  456.                 }
  457.             else
  458.                 Local_Intersection = New_Intersection;
  459.  
  460.             Intersection_Found = TRUE;
  461.             }
  462.         }
  463.  
  464.     if (Intersection_Found) {
  465.         Determine_Surface_Colour (Local_Intersection, Colour, Ray, FALSE);
  466.         free (Local_Intersection);
  467.         }
  468.     }
  469.